package com.settlement.system.handler.mybatisplus;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.handler.DataPermissionHandler;
import com.settlement.system.common.annotation.StorePermission;
import com.settlement.system.common.annotation.RoleAndStorePermission;
import com.settlement.system.common.util.SecurityUtils;
import com.settlement.system.mapper.security.userdetails.SysUserDetails;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;

import java.lang.reflect.Method;
import java.util.Set;

/**
 * 数据权限控制器
 *
 * @author zc
 * @since 2021-12-10 13:28
 */
@Slf4j
public class MyDataPermissionHandler implements DataPermissionHandler {

    @Override
    @SneakyThrows
    public Expression getSqlSegment(Expression where, String mappedStatementId) {
        // 超级管理员不受数据权限控制
        if (SecurityUtils.isRoot()) {
            return where;
        }
        Class<?> clazz = Class.forName(mappedStatementId.substring(0, mappedStatementId.lastIndexOf(StringPool.DOT)));
        String methodName = mappedStatementId.substring(mappedStatementId.lastIndexOf(StringPool.DOT) + 1);
        Method[] methods = clazz.getDeclaredMethods();
        for (Method method : methods) {
            RoleAndStorePermission roleAndStorePermission = method.getAnnotation(RoleAndStorePermission.class);
            if (ObjectUtils.isNotEmpty(roleAndStorePermission) && method.getName().equals(methodName)){
                return roleAndStoreDataScopeFilter(where);
            }
            StorePermission storePermission = method.getAnnotation(StorePermission.class);
            if (ObjectUtils.isNotEmpty(storePermission) && method.getName().equals(methodName)){
                return storeDataScopeFilter(where);
            }
        }
        return where;
    }
    /**
     * 构建过滤条件
     * 根据用户角色和所属店铺动态生成sql
     * @param where 当前查询条件
     * @return 构建后查询条件
     */
    @SneakyThrows
    public static Expression roleAndStoreDataScopeFilter(Expression where) {
        // 获取当前用户的数据权限
        String appendSqlStr = null;
        SysUserDetails user = SecurityUtils.getUser();
        if (user != null) {
            String storeIds = user.getStoreIds();
            if (StringUtils.isBlank(storeIds)) {
                log.info("当前用户没有配置所属店铺，所以没有查询到数据");
                appendSqlStr = "store_id = 'NULL'";
            } else {
                appendSqlStr = "store_id in (";
                String[] keys = storeIds.split(",");
                for (String key : keys) {
                    appendSqlStr += "'" + key + "',";
                }
                appendSqlStr = appendSqlStr.substring(0, appendSqlStr.length() - 1);
                appendSqlStr += ")";
            }
            Set<String> roles = user.getRoles();
            appendSqlStr += "and belong_role in (";
            for (String role : roles) {
                appendSqlStr += "'" + role + "',";
            }
            appendSqlStr = appendSqlStr.substring(0, appendSqlStr.length() - 1);
            appendSqlStr += ")";
        }
        if (StrUtil.isBlank(appendSqlStr)) {
            return where;
        }
        Expression appendExpression = CCJSqlParserUtil.parseCondExpression(appendSqlStr);
        if (where == null) {
            return appendExpression;
        }
        return new AndExpression(where, appendExpression);
    }

    /**
     * 构建过滤条件
     * 根据用户所属店铺动态生成sql
     * @param where 当前查询条件
     * @return 构建后查询条件
     */
    @SneakyThrows
    public static Expression storeDataScopeFilter(Expression where) {
        // 获取当前用户的数据权限
        String appendSqlStr = "";
        SysUserDetails user = SecurityUtils.getUser();
        if (user != null) {
            String storeIds = user.getStoreIds();
            if (StringUtils.isBlank(storeIds)) {
                log.info("当前用户没有配置所属店铺，所以没有查询到数据");
                appendSqlStr = "store_id = 'NULL'";
            }else{
                appendSqlStr = "store_id in (";
                String[] keys = storeIds.split(",");
                for (String key : keys) {
                    appendSqlStr += "'" +key + "',";
                }
                appendSqlStr = appendSqlStr.substring(0, appendSqlStr.length() - 1);
                appendSqlStr += ")";
            }
        }
        if (StrUtil.isBlank(appendSqlStr)) {
            return where;
        }
        Expression appendExpression = CCJSqlParserUtil.parseCondExpression(appendSqlStr);
        if (where == null) {
            return appendExpression;
        }
        return new AndExpression(where, appendExpression);
    }
}

